home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 11 / Cream of the Crop 11-1.iso / comm / 110a115a.zip / WINHOST.ZIP / WINHOST.SLT < prev   
Text File  |  1995-12-22  |  53KB  |  1,887 lines

  1. //
  2. //   W I N H O S T . S L T
  3. //
  4. //   Copyright (C) 1988-1995 deltaComm Development.
  5. //
  6. //   - Written by Colin Sampaleanu.
  7. //   - Modifications by Jeff Woods, Feb '91, to add help function and support
  8. //     for locked modems.
  9. //   - Modifications by Dan Horn, Nov '92, fixed 'floating' timer bug.
  10. //   - Thanks to Jon Fleming for his help in porting this to Windows.
  11. //   - Modifications for hot keys and logins, fixes for chat mode and
  12. //     <=9600 baud remote dos shells in Dec '94 by Sean Palmer
  13. //   - Modifications to Connect baud parsing Jan '95 by Sean Palmer
  14. //   - Modifications to allow ANSI and RIP displays Feb '95 by Jeff Smith
  15. //   - Message system added March '95 by Jeff Smith
  16. //
  17. //   This is a Host Mode for Telix, written as a script file.
  18. //   To configure Host Mode parameters such as passwords, run the 'WCONFIG'
  19. //   script. That script is run automatically if the Host Mode configuration
  20. //   file 'WINHOST.CNF' is missing.
  21. //
  22. //   This script will only work with Hayes compatible modems, but may be
  23. //   modified for operation with other modems.
  24. //
  25. //////////////////////////////////////////////////////////////////////////////
  26.  
  27. #stack 1536  // Increased stack size
  28.  
  29. // Parameters which are configured from the WinHost configuration file
  30.  
  31. str host_downloads[64],         // Default where users may download from
  32.     host_uploads[64],           // Default where uploaded files go
  33.     host_message[64];           // Default used by message system
  34.  
  35. int direct_connect = 0,         // 0 = using a modem
  36.     modem_lock = 0,
  37.     closed_sys = 0;             // 0 = users may sign up on line if not
  38.                                 //  found in the config file
  39.  
  40. // Various global variables
  41.  
  42. str current_caller[31],         // storage of current caller's name
  43.     our_dir[64];                // Winhost directory (either Telix's
  44.                                 //  scripts directory or the contents
  45.                                 //  of the HOST2DIR environment variable
  46.                                 //  if it exists)
  47.  
  48.  
  49. int finished_caller,            // set to TRUE when must return to top
  50.     local_mode,                 // set to TRUE when local test mode
  51.     access_level,               // access level of current caller
  52.     carrier_counts = 1,         // TRUE if should watch Carrier signal
  53.     already_connected = 0,
  54.     exit_requested = 0,         // set to TRUE if Sysop has pressed Esc
  55.     connection_lost = 0,        // set to TRUE when carrier lost
  56.     kill_user = 0,              // set to TRUE when user must be purged
  57.     min_user_name = 5,          // Minimum length of user's name
  58.     user_has_own_dir;           // Flag to restrict the user to one dir
  59.  
  60. int old_scr_chk_key,            // storage for some system variables
  61.     old_cisb_auto,              // which we have to modify and put
  62.     old_zmod_auto,              // back to what they were when done
  63.     old_sound,
  64.     RIP_On, ANSI_On;            // Flag ANSI and RIP capability
  65.  
  66. str old_down_dir[64],
  67.     old_up_dir[64],
  68.     tfw_down_dir[64],
  69.     tfw_up_dir[64],
  70.     old_usage_fname[64];
  71.  
  72. int ndx_fil, mssg_num,          // Message system variables
  73.     mssg_time, mssg_priv;       // used by the index file
  74. str mssg_to[30], mssg_from[30], // "message.ndx"
  75.     mssg_subj[30];
  76.  
  77. #INCLUDE "WHUTILS.SLT"          // Functions which are shared with the
  78.                                 //  configuration managements script
  79.  
  80. //////////////////////////////////////////////////////////////////////////////
  81. //////////////////////////////////////////////////////////////////////////////
  82.  
  83. main() {
  84.   int c;
  85.   str s[80], filnam[64];
  86.  
  87.   tfw_up_dir = _up_dir;
  88.   tfw_down_dir = _down_dir;
  89.   clear_scr;
  90.  
  91.   get_our_dir;
  92.  
  93.   if (read_host_config_file == -1) {
  94.      prints("Unable to read WINHOST.CNF...");
  95.      prints("Running WCONFIG, the Host Mode configuration script.^M^J");
  96.      s = our_dir;
  97.      strcat (s, "WCONFIG");
  98.      calld(s);
  99.      if (read_host_config_file() == -1) {
  100.         prints("Still unable to read WINHOST.CNF. Aborting Host Mode.^M^J");
  101.         return -1;
  102.      }
  103.   }
  104.  
  105.   prints ("Checking existence of directories ...");
  106.   if (!(check_directory(host_downloads)
  107.      && check_directory(host_uploads)
  108.      && check_directory(host_message))) {
  109.     prints("Aborting Host Mode.");
  110.     return -2;
  111.   }
  112.  
  113.   old_scr_chk_key = _scr_chk_key;
  114.   _scr_chk_key = 0;
  115.   old_cisb_auto = _cisb_auto;
  116.   _cisb_auto = 0;
  117.   old_zmod_auto = _zmod_auto;
  118.   _zmod_auto = 0;
  119.   old_sound = _sound_on;
  120.   _sound_on = 0;
  121.   old_down_dir = _down_dir;
  122.   old_usage_fname = _usage_fname;
  123.  
  124.   s = our_dir;
  125.   strcat (s, "HOST2.LOG");
  126.   usagelog (s);
  127.  
  128.   carrier_counts = !direct_connect;
  129.   already_connected = (carrier_counts && carrier());
  130.  
  131.   filnam=host_message;
  132.   strcat(filnam, "message.ndx");
  133.   if (filefind(filnam, 0))   {
  134.    ndx_fil=fopen(filnam, "r+");
  135.    if (ndx_fil)
  136.      update_ndx_file();   // scan index file for msgs more than
  137.                           // a certain age, & delete them
  138.   }
  139.   else   {     // Create the index file
  140.    ndx_fil=fopen(filnam, "w+");
  141.    mssg_from="Internal";
  142.    mssg_to="Internal";
  143.    mssg_priv=1;
  144.    mssg_time=curtime();
  145.    mssg_subj="Time Index";
  146.    ndx_write(0);
  147.   }
  148.  
  149.  
  150.   while (1) {
  151.     _down_dir = host_uploads;   // these are reversed because we are the Host
  152.     old_up_dir = _up_dir;
  153.     _up_dir = host_downloads;   // these are reversed because we are the Host
  154.     user_has_own_dir = 0;
  155.     if (!direct_connect && !already_connected) {
  156.       if (!modem_lock)
  157.         set_cparams(modem_lock, 0, 8, 1);
  158.       delay_scr(3);
  159.       prints("Sending Modem Init string...");
  160.       cputs_tr(_mdm_init_str);
  161.       delay_scr(25);
  162.       prints("Sending Auto-Answer string...");
  163.       cputs_tr(_auto_ans_str);
  164.       delay_scr(10);
  165.     }
  166.  
  167.     finished_caller = kill_user = 0;
  168.  
  169.     if (direct_connect)
  170.       carrier_counts = 0;
  171.     else {
  172.       carrier_counts = 1;
  173.       local_mode = 0;
  174.       prints("^M^JHost Mode: Waiting for call...");
  175.       prints("(Press Esc to exit, or 'L' for local test mode).^M^J");
  176.  
  177.       do {
  178.         if (carrier()) break;
  179.  
  180.         if ((c = inkey())==27) {
  181.           exit_requested = 1;
  182.           break;
  183.         }
  184.         else if (c==' ') { cputs("ata^m"); c=0; }
  185.         else if (toupper(c) == 'L') {             // local test mode
  186.           prints("Local test mode entered");
  187.           local_mode = 1;
  188.           carrier_counts = 0;
  189.           break;
  190.         }
  191.       } while (1);
  192.     }
  193.  
  194.     if (!exit_requested) {
  195.       prints("Incoming call. Sysop: press Esc to exit, or END to terminate user.");
  196.       _user_int3 = 0;
  197.  
  198.       do_one_caller();
  199.       if ((connection_lost || kill_user) && carrier_counts && carrier())
  200.         hangup();             // make sure nobody sneaks in
  201.     }
  202.     already_connected = 0;
  203.     if (exit_requested) {
  204.       if (!carrier() && !direct_connect) {
  205.         prints("Sending Modem Init string...");
  206.         cputs_tr(_mdm_init_str);
  207.       }
  208.       _scr_chk_key = old_scr_chk_key;
  209.       _cisb_auto = old_cisb_auto;
  210.       _zmod_auto = old_zmod_auto;
  211.       _sound_on = old_sound;
  212.       _down_dir = tfw_down_dir;
  213.       _up_dir = tfw_up_dir;
  214.       prints("^M^JHost mode script finished.");
  215.       usagelog("*CLOSE*");
  216.       _usage_fname = old_usage_fname;
  217.       if (_user_int3 == 99)
  218.         return 1;
  219.       else
  220.         return 0;
  221.     }
  222.   }
  223. }
  224.  
  225. //////////////////////////////////////////////////////////////////////////////
  226.  
  227. host_help (str mode, str option) {
  228.  
  229.   str fname[64];
  230.  
  231.   fname = our_dir;
  232.   strcat (fname, mode);
  233.   strcat (fname, "_HELP_");
  234.   StrCat (fname, option);
  235.   StrCat (fname, ".TXT");
  236.  
  237.   if (FileFind (fname, 0)) {
  238.     type_our_file (fname);
  239.     return 1;
  240.   }
  241.   else {
  242.     printsc ("^MCan't find help file ");
  243.     prints (fname);
  244.     return (0);
  245.   }
  246. }
  247.  
  248. //////////////////////////////////////////////////////////////////////////////
  249.  
  250. do_one_caller() {
  251.  
  252.   str strn[80], fname[64],  s[80], temporary[1],
  253.       num[10], CHKSTR[20];
  254.   int option, status, c, i, i2, f, len, TIMR;
  255.  
  256.   access_level = 1;
  257.  
  258. //  flushbuf();
  259.  
  260.   if (already_connected)
  261.     prints("Already connected, or modem Carrier Detect switch improperly set!");
  262.   else if (carrier_counts)
  263.     determine_baud();
  264.  
  265.   if (!local_mode) delay_scr(20);
  266.  
  267.   flushbuf();
  268.   if (local_mode) {
  269.     ansi_on=rip_on=0;
  270.     s=gety();              //detect local ansi
  271.     host_send("^[[2A");
  272.     if ((s-gety())==2) {
  273.       ansi_on=1;
  274.       host_send("^[[2B");
  275.       host_send("^A|H");   //detect local rip
  276.       if (gety()==0) {
  277.         rip_on=1;
  278.         }
  279.       else host_send("^H^H^H   ^H^H^H");
  280.       }
  281.     else host_send("^H^H^H   ^H^H^H");
  282.     gotoxy(1, s);     //fix cursor
  283.     }
  284.   else {
  285.     Ansi_On=0;
  286.     Rip_On=0;
  287.     chkstr="";
  288.     cputs("^M^[[6n^H^H^H^H    ^H^H^H^H");
  289.     timr=timer_start(10);
  290.     do {
  291.       if (cinp_cnt()) {
  292.         s=cgetc();
  293.         strcat(chkstr, s);
  294.         }
  295.       }
  296.     while (!time_up(timr));
  297.     timer_free(timr);
  298.     if ((strpos(chkstr, "^[[", 0)>=0) && (strpos(chkstr, "R", 1)>=0))
  299.      {
  300.       ANSI_On=1;
  301.       chkstr="";
  302.       cputs("^M^[[!^H^H^H   ^H^H^H");
  303.       timr=timer_start(10);
  304.       do
  305.        {
  306.         if (cinp_cnt()) {
  307.           s=cgetc();
  308.           strcat(chkstr, s);
  309.           }
  310.        }
  311.       while (!time_up(timr));
  312.       timer_free(timr);
  313.       RIP_On = (strpos(chkstr, "RIPSCRIP", 0) >= 0);
  314.      }
  315.   }
  316.   type_our_file("LOGO");
  317.  
  318.   if (!get_user_name()) {
  319.     ustamp("Failed logon attempt", 1, 0);
  320.     return;
  321.     }
  322.  
  323.   access_level = setup_user(3);
  324.  
  325.   if (access_level) {
  326.     ustamp("Logon by ", 1, 0);
  327.     ustamp(current_caller, 0, 1);
  328.   }
  329.   else {
  330.     ustamp("Failed logon attempt by ", 1, 0);
  331.     ustamp(current_caller, 0, 1);
  332.     send_goodbye();
  333.     if (carrier_counts) {
  334.       delay_scr(10);
  335.       hangup();
  336.     }
  337.     return;
  338.   }
  339.  
  340.   type_our_file("WELCOME");
  341.  
  342.   while (1) {
  343.     if (finished_caller)
  344.     return;
  345.  
  346.     if (access_level == 3) {
  347.       if (type_our_file("MMENU3") == -1)
  348.         host_send("^M^JFiles  Type  Upload  Download  Shell  Chat  Help  Message  Goodbye ? ");
  349.     }
  350.     else {
  351.       if (type_our_file ("MMENU") == -1)
  352.           host_send("^M^JFiles  Type  Upload  Download  Chat  Help  Message  Goodbye ? ");
  353.     }
  354.  
  355.     host_send ("^M^JCommand: ");
  356.     host_input_strn(strn, 1, 1);
  357.     option = toupper(subchr(strn, 0));
  358.     host_send("^M^J");
  359.  
  360.     if (option == 'H') {               // Help
  361.       host_send("^M^JWhich item above do you wish help on? ");
  362.       host_input_strn(strn, 1, 1);
  363.       substr (strn, 0, 1, strn);
  364.       strupper (strn);
  365.       Host_send("^M^J");
  366.       host_help( "H", strn);
  367.     }
  368.  
  369.     if (option == 'F') {               // Files directory
  370.       if (access_level >= 2) {
  371.         host_send("Enter 'filespec' or press Return for *.*,^M^J: ");
  372.         host_input_strn(fname, 64, 1);
  373.         host_send("^M^J");
  374.         ustamp ("Requested file listing of ", 1, 0);
  375.         ustamp (fname, 0, 1);
  376.  
  377.         if (strcmpi (fname, "") == 0) {
  378.           fname = "*.*";
  379.         }
  380.  
  381.         if (just_filename(fname)) {
  382.           strn = _up_dir;
  383.           strcat(strn, fname);
  384.         }
  385.         else if (user_has_own_dir == 1) {
  386.           host_send ("^M^JAccess outside ");
  387.           host_send (_up_dir);
  388.           host_send (" not allowed^M^J");
  389.           strn = _up_dir;
  390.           strcat(strn, "*.*");
  391.         }
  392.         else {
  393.           len = strlen (fname);
  394.           substr (fname, len - 1, 1, temporary);
  395.           if (strcmpi (temporary, "\") == 0) {
  396.             strn = fname;
  397.             strcat (strn, "*.*");
  398.           }
  399.           else strn = fname;
  400.         }
  401.       }
  402.       else {
  403.         strn = _up_dir;
  404.         strcat(strn, "*.*");
  405.         ustamp ("Requested listing of files", 1, 1);
  406.       }
  407.  
  408.       host_show_directory(strn);
  409.       ustamp ("Displayed ", 1, 0);
  410.       ustamp (strn, 0, 1);
  411.     }
  412.  
  413.     else if (option == 'T') {          // Type a file
  414.       host_send("Type what file? ");
  415.       host_input_strn(strn, 64, 1);
  416.       host_send("^M^J");
  417.       ustamp ("Requested to type ", 1, 0);
  418.       ustamp (strn, 0, 1);
  419.  
  420.       if ((access_level == 1) || (user_has_own_dir == 1))
  421.         fnstrip(strn, 3, fname);
  422.       else
  423.         fname = strn;
  424.  
  425.       if (just_filename(fname)) {
  426.         strn = _up_dir;
  427.         strcat(strn, fname);
  428.         fname = strn;
  429.       }
  430.  
  431.       if (!filefind(fname, 0, strn)) {
  432.         host_send("Unable to find ");
  433.         host_send(fname);
  434.         continue;
  435.       }
  436.  
  437.       get_extension(fname, strn);
  438.       if (strcmpi(strn,"ZIP")==0 ||
  439.           strcmpi(strn,"ARJ")==0)
  440.       {
  441.         host_send("Unable to type ");
  442.         host_send(fname);
  443.         continue;
  444.       }
  445.  
  446.       type_file(fname);
  447.       ustamp ("Typed ", 1, 0);
  448.       ustamp (fname, 0, 1);
  449.     }
  450.  
  451.     else if (option == 'M') {          // Message system
  452.        do {
  453.          if (type_our_file("mssgmenu")==-1)
  454.            host_send("Read  Write  Quit ?");
  455.  
  456.          i=host_input(1);
  457.          i=toupper(i);
  458.          if (i=="R") read_mssg();
  459.          else if (i=="W") write_mssg();
  460.         }
  461.         while (i!='Q');
  462.     }
  463.  
  464.     else if (option == 'G') {          // Goodbye (Hang-up)
  465.       // Confirm selection
  466.       host_send("Are you sure you want to log off the system (y/N)? ");
  467.       i=host_input(1);
  468.       i=toupper(i);
  469.       if (i=="Y") {
  470.         send_goodbye ();
  471.         ustamp("User logged off.", 1, 1);
  472.         if (carrier_counts) {
  473.           delay_scr(10);
  474.           hangup();
  475.         }
  476.         return;
  477.       }
  478.     }
  479.  
  480.     else if (option == 'C') {          // Chat mode
  481.       prints("Sysop: Press Space to chat, any other key not to.^M^J");
  482.       c = 0;
  483.       _sound_on = 1;
  484.       for (i = 8; i && !c; --i) {
  485.         host_send (".");
  486.         if (carrier_counts && !carrier()) {
  487.           prints("^M^JConnection has been lost, call terminated.^M^J");
  488.           connection_lost = 1;
  489.           finished_caller = 1;
  490.           break;
  491.         }
  492.         cputc('^G');
  493.         tone(523, 20);
  494.         tone(659, 20);
  495.         tone(523, 20);
  496.         tone(659, 20);
  497.         tone(523, 20);
  498.         tone(659, 20);
  499.         delay(9);
  500.         c = inkey();
  501.       }
  502.       _sound_on = 0;
  503.       host_send ("^M^J");
  504.       if (finished_caller)
  505.         continue;
  506.       if (c != ' ') {
  507.         host_send("Sorry, the Sysop is unavailable^M^J");
  508.         continue;
  509.       }
  510.       host_send("The sysop is here!^M^JEnable your chat mode or local echo option.^M^J");
  511. /* echo characters to remote will confuse it's chat mode.  Users without a chat mode should
  512.    get TfW or turn local echo option on during chat.
  513.       chatmode(!local_mode,1); //start chat, no echo if local */
  514.       chatmode(0,1);
  515.  
  516.       status_wind("Press Ctrl-X to terminate chat",30);
  517.       while (1) {
  518.         if (waitfor("^X",1)) break;
  519.       }
  520.       chatmode(0,0);
  521. //      chatmode(!local_mode,0); //end chat
  522.       host_send("^M^JChat mode ended.  Exit your chat mode or disable the local echo option.^M^J");
  523.     }
  524.  
  525.     else if (option == 'U') {          // User upload
  526.       option = host_get_prot();
  527.       if (!option)
  528.         continue;
  529.  
  530.       ustamp ("Upload ", 1, 0);
  531.       status = 1;
  532.       if (option == 'Y' || option == 'Z' || option == 'E') {
  533.         ustamp ("with name-transferring protocol ", 0, 1);
  534.         send_transfer_msg();
  535.         status = receive(option, "");
  536.       }
  537.       else {
  538.         host_send("Upload what file? ");
  539.         host_input_strn(strn, 48, 1);
  540.         host_send("^M^J");
  541.           if (!strn)
  542.             continue;
  543.           ustamp (strn, 0, 1);
  544.           if ((access_level == 1) || (user_has_own_dir == 1)) // if access 1, name and ext only
  545.             fnstrip(strn, 3, fname);
  546.           else
  547.             fname = strn;
  548.  
  549.           if (just_filename(fname)) {
  550.             strn = _down_dir;
  551.             strcat(strn, fname);
  552.             fname = strn;
  553.           }
  554.  
  555.           if (filefind(fname, 23, strn)) {
  556.             host_send("File already exists!^M^J");
  557.             ustamp ("File already exists", 1, 1);
  558.           }
  559.           else {
  560.             send_transfer_msg();
  561.             status = receive(option, fname);
  562.           }
  563.         }
  564.  
  565.         if (status == -2) {                      // Carrier lost
  566.           connection_lost = finished_caller = 1;
  567.           ustamp ("Lost carrier", 1, 1);
  568.         }
  569.         else if (status == -1) {
  570.           host_send("^M^J^M^J^GOne or more files not received!^M^J");
  571.           ustamp ("One or more files not received", 1, 1);
  572.         }
  573.         else {
  574.           ustamp ("Transfer complete", 1, 1);
  575.         }
  576.       }
  577.  
  578.     else if (option == 'D') {          // User download
  579.       option = host_get_prot();
  580.       if (!option)
  581.         continue;
  582.       host_send("Download what file(s)? ");
  583.       host_input_strn(strn, 48, 1);
  584.       host_send("^M^J");
  585.       if (!strn)
  586.         continue;
  587.       ustamp ("Attempt to download ", 1, 0);
  588.       ustamp (strn, 0, 1);
  589.       if ((access_level == 1) || (user_has_own_dir == 1)) // if not level 2, keep only name & ext
  590.         fnstrip(strn, 3, fname);
  591.       else
  592.         fname = strn;
  593.       if (just_filename(fname)) {
  594.         strn = _up_dir;
  595.         strcat(strn, fname);
  596.         fname = strn;
  597.       }
  598.  
  599.       if (!filefind(fname, 0, strn)) {
  600.         host_send("Unable to find any matching file(s)!^M^J");
  601.         ustamp ("No such file", 1, 1);
  602.         continue;
  603.       }
  604.  
  605.       status = 1;
  606.       send_transfer_msg();
  607.       status = send(option, fname);
  608.       if (status == -2) {                      // Carrier lost
  609.         connection_lost = finished_caller = 1;
  610.         ustamp ("Lost carrier", 1, 1);
  611.       }
  612.       else if (status == -1) {
  613.         host_send("^M^J^M^J^GOne or more files not sent!^M^J");
  614.         ustamp ("One or more files not sent", 1, 1);
  615.       }
  616.       else {
  617.         ustamp ("Transfer complete", 1, 1);
  618.       }
  619.     }
  620.  
  621.     else if (option == 'S') {          // Remote shell
  622.       ustamp ("Attempted shell", 1, 1);
  623.       if (access_level == 3) {
  624.         host_send("Type EXIT and then press Enter to come back.^M^J");
  625.         if (get_baud() == 300)
  626.           delay_scr(10);
  627.         if (local_mode)
  628.           dos("", 0);
  629.              // See if user has prepared a custom file for shell operation
  630.              // and call that if it exists
  631.         else {
  632.           if (filefind("RSHELL.BAT", 0, strn))
  633.             do_remote_shell("RSHELL.BAT");
  634.           else {  // otherwise make our own temporary batch file for redirection
  635.             if (get_port() != 1 && get_port() != 2) {
  636.               host_send("Remote Shell not supported on this comm port due to DOS limits!^M^J");
  637.             }
  638.             else {
  639.              // now want to make a temporary batch file which will be
  640.              // called to redirect DOS input and output, then shell to
  641.              // another copy of the command interpreter
  642.               f = fopen("HOSTTEMP.BAT", "w");
  643.               if (f) {
  644.                 if (get_baud()>9600) {
  645.                   status_wind("Attempting to shell to dos at over 9600 baud",50);
  646.                   ustamp("DOS shell baud > 9600",0,1);
  647.                   }
  648.                 fputs("MODE ", f);    // this command informs dos of the port rate
  649.                 strn = "COMx";
  650.                 setchr(strn, 3, get_port() + '0'); // get right name to redirect
  651.                 fputs(strn, f);                    // save strn for later
  652.                 fputc(" baud=", f);
  653.                 itos(get_baud(), num);
  654.                 fputs(num, f);
  655.                 fputs(" parity=", f);
  656.                 switch (get_parity()) {
  657.                   case 1:  fputc('E', f);
  658.                   case 2:  fputc('O', f);
  659.                   case 3:  fputc('M', f);
  660.                   case 4:  fputc('S', f);
  661.                   default: fputc('N', f);
  662.                 }
  663.                 fputs(" data=", f);
  664.                 itos(get_dataB(), num);
  665.                 fputs(num, f);
  666.                 fputs(" stop=", f);
  667.                 itos(get_stopB(), num);
  668.                 fputs(num, f);
  669.                 fputs("^M^J", f);
  670.  
  671.                 fputs("CTTY ", f);           // write to batch file
  672.                 fputs(strn, f);              // this command actually makes the shell work
  673.                 fputs("^M^J", f);
  674.                 if (getenv ("COMSPEC", s) == 0)
  675.                   s = "COMMAND.COM";
  676.  
  677.                 fputs (s, f);
  678.                 fputs("^M^J", f);
  679.                 fputs("CTTY CON^M^J", f);
  680.                 fputs("EXIT^M^J", f);
  681.  
  682.                 fclose(f);                   // close the file
  683.  
  684.                 if (!local_mode)             // call batch file
  685.                   do_remote_shell("HOSTTEMP.BAT");
  686.               }
  687.               else
  688.                 host_send("Can't open temporary batch file!^M^J");
  689.             }
  690.           }
  691.         }
  692.       }
  693.       else ustamp ("Request denied", 1, 1);
  694.     }
  695.  
  696.     else if (option == '^Z') {          // Shut down Host Mode
  697.       if (access_level == 3) {
  698.         host_send("Shutting down Host mode. ");
  699.         ustamp("User shut down Host Mode.", 1, 1);
  700.         send_goodbye ();
  701.         ustamp("User logged off.", 1, 1);
  702.         if (carrier_counts)
  703.           hangup();
  704.         finished_caller = 1;
  705.         exit_requested = 1;
  706.       }
  707.     }
  708.   }
  709. }
  710.  
  711. //////////////////////////////////////////////////////////////////////////////
  712.  
  713. do_remote_shell(str batfile) {
  714.   str savedConn[80];                   //holds saved connect device's name
  715.  
  716.   //here we make a new connect device with a port of 0 which causes the
  717.   //device to not be attached to any specific port. Useful to
  718.   //keep Telix from using any ports temporarily.
  719.   if (makeConnectDevice("__NULL__","2400bps Generic",0,0,0))
  720.   {
  721.     connectDeviceName(0,savedConn);      //get current device name
  722.     if (set_ConnectDevice("__NULL__",2)) //selecting a port 0 device won't
  723.     {                                    //disturb the current device's connection
  724.       dos(batfile);
  725.       set_ConnectDevice(savedConn,1);  //restore previous connect device
  726.     }                                  //without sending init string
  727.     killConnectDevice("__NULL__");
  728.   }
  729. }
  730.  
  731. //////////////////////////////////////////////////////////////////////////////
  732.  
  733. host_get_prot() {
  734.  
  735.   str prot[1], strn[1], s[64];
  736.  
  737.   int Option;
  738.  
  739.   prot = "H";
  740.  
  741.   while (strcmpi (prot, "H") == 0) {
  742.  
  743.     if (type_our_file ("PMENU") == -1) {
  744.       host_send("^M^JXmodem  xmodem-Crc  xmodem-1k  xmodem-1k-G  Ymodem  ymodEm-g  Zmodem  Kermit^M^J");
  745.       host_send("Help Cancel^M^J");
  746.     }
  747.  
  748.     host_send("Which protocol, or H for help ? ");
  749.     host_input_strn(prot, 1, 1);
  750.     strupper (prot);
  751.     host_send("^M^J");
  752.  
  753.     if (strcmpi (prot, "H") == 0) {
  754.       host_send ("^M^JHelp on which protocol, or ^"A^" for ALL? ");
  755.       host_input_strn (strn, 1, 1);
  756.       substr (strn, 0, 1, strn);
  757.       strupper (strn);
  758.       Host_send("^M^J");
  759.       host_help( "P", strn);
  760.     }
  761.  
  762.     if (strposi("XC1GYEZKH", prot, 0) == -1)  // if illegal prot or cancel
  763.       prot = "";                              // return 0
  764.   }
  765.  
  766.   return (toupper(subchr(prot, 0)));
  767.  
  768. }
  769.  
  770. //////////////////////////////////////////////////////////////////////////////
  771.  
  772. send_transfer_msg() {
  773.  
  774.   host_send("Ready to transfer file(s)... Press Ctrl-X at least twice to abort^M^J");
  775. }
  776.  
  777. //////////////////////////////////////////////////////////////////////////////
  778. // Determine the baud rate once a Carrier Detect Signal has been detected
  779. // Since no characters were read, the 'CONNECT' string should still be
  780. // in the receive buffer.
  781.  
  782. determine_baud() {
  783.  
  784.   int tconnect;
  785.   int tmark, stat, c;
  786.   int new_baud = 0;
  787.  
  788.   str cstring[20];
  789.  
  790.   printsc("Determining baud... ");
  791.  
  792.   track_free(0);                // clear all existing tracks
  793.  
  794.   tconnect = track(_connect_str, 0);  // check for connect string
  795.  
  796.   tmark = timer_start(30);      // wait up to 3 seconds for string
  797.  
  798.   while (!time_up(tmark)) {
  799.     if (!carrier()) {
  800.       track_free(0);            // clear all existing tracks
  801.       timer_free(tmark);        // free existing timer
  802.       return 0;
  803.     }
  804.  
  805.     if (cinp_cnt()) {
  806.       printc_trm(c=cGetC);      // does tracks too
  807. //      printc(c=cGetC);
  808. //      track_addChr(c);
  809.       }
  810.  
  811.     if (track_hit(0) != tConnect) continue;
  812.  
  813.     while (1) {
  814.       while (!cinp_cnt()) ;
  815.       if ((c=cgetc)>' ') break;
  816.       printc(c);
  817.       }
  818.     while(1) {
  819.       printc(c);
  820.       if ((c>='0') && (c<='9'))
  821.         new_baud = new_baud * 10 + c - '0';
  822.       else break;
  823.       while (!cinp_cnt) ;
  824.       c=cgetc();
  825.     }
  826.     printc(c);
  827.  
  828.     if (!new_baud) new_baud = 300;
  829.  
  830.     break;                      // have baud rate, get out
  831.   }
  832.  
  833.   track_free(0);                // clear all existing tracks
  834.   timer_free(tmark);            // free existing timer
  835.  
  836.   if (!new_baud) {              // time-up without CONNECT string
  837.     prints("Failed!");
  838.     return 0;
  839.   }
  840.  
  841. //  printn(new_baud);
  842. //  newLine();
  843.   setDCERate(new_baud);         // Let TFW know
  844.   return 1;                     // indicate success
  845.  
  846. }
  847.  
  848. //////////////////////////////////////////////////////////////////////////////
  849. // Allow user to read messages
  850. read_mssg()
  851. {
  852.  str read_fil[64], buf[64];
  853.  int mcode, rflag, position, i;
  854.  mcode=0;
  855.  host_send("^M^J Read all public mail (y/n): ");
  856.  i=toupper(host_input(1));
  857.  if (i=='Y') mcode=2;
  858.  else
  859.   {
  860.    host_send("^M^J Read mail to 'All' (y/n): ");
  861.    i=toupper(host_input(1));
  862.    if (i=='Y') mcode=1;
  863.   }
  864.  host_send("^M^J");
  865.  fseek(ndx_fil, 0, 0);
  866.  while (ndx_read()) {
  867.     rflag=0;
  868.     if ((strcmpi(mssg_to, current_caller)==0)
  869.      and (mssg_priv < 2)) rflag=1;
  870.     else
  871.      if ((strcmpi(mssg_to, "ALL")==0) and (mcode>0)
  872.       and (mssg_priv == 0)) rflag=1;
  873.      else
  874.       if ((mssg_priv==0) and (mcode==2)) rflag=1;
  875.     if (rflag)
  876.      {
  877.       host_send("^M^J  From: ");
  878.       host_send(mssg_from);
  879.       host_send("   To: ");
  880.       if (mssg_to==0) host_send("All");
  881.       else host_send(mssg_to);
  882.       host_send("   ");
  883.       date(mssg_time, read_fil);
  884.       host_send(read_fil);
  885.       host_send("^M^J  Subject: ");
  886.       host_send(mssg_subj);
  887.       host_send("^M^J^M^J   Read Message (y/n)");
  888.       i=host_input(1);
  889.       i=toupper(i);
  890.       host_send("^M^J");
  891.       if (i=='Y')
  892.        {
  893.         itos(mssg_num, buf);
  894.         read_fil=host_message;
  895.         strcat(read_fil, "M");
  896.         strcat(read_fil, buf);
  897.         strcat(read_fil, ".MSG");
  898.         type_file(read_fil);
  899.         host_send("^M^J");
  900.        }
  901.       if (strcmpi(mssg_to, current_caller)==0)
  902.        {
  903.         host_send(" Delete Message (y/n)");
  904.         i=host_input(1);
  905.         i=toupper(i);
  906.         if (i=='Y') delete_mssg(mssg_num);
  907.         host_send("^M^J");
  908.        }
  909.      }
  910.    }
  911. }
  912.  
  913. // Allow user to write messages
  914. write_mssg()
  915. {
  916.  str ans[85], fn[64], wrd[80];
  917.  int cnt, i, mssgdone, f;
  918.  f=fopen("edit.msg", 'w');
  919.  host_send("^M^J^M^J");
  920.  host_send(" Private message (y/n)");
  921.  do
  922.   i=toupper(host_input(1));
  923.  while ((i!='Y') and (i!='N'));
  924.  if (i=='Y') mssg_priv=1;
  925.  else mssg_priv=0;
  926.  host_send("^M^J To: ");
  927.  host_input_strn(mssg_to, 30, 1);
  928.  host_send("^M^J Subject: ");
  929.  host_input_strn(mssg_subj, 30, 1);
  930.  host_send("^M^J");
  931.  host_send(" Enter message:^M^J");
  932.  ANS=wrd=""; CNT=1;
  933.  MSSGDONE=0;
  934.  do
  935.   {
  936.    i=host_input(1);
  937.    ++CNT;
  938.    if (i==13)
  939.      {
  940.       strcat(ans, wrd);
  941.       wrd="";
  942.       host_send("^M^J");
  943.       IF (ANS=="") MSSGDONE=1;
  944.       strcat(ans, "^m");
  945.       fputs(ans, f);
  946.       ANS="";
  947.       CNT=1;
  948.      }
  949.    else
  950.    if (i==8)
  951.      {
  952.       CNT=CNT-2;
  953.       IF (CNT<0) CNT=0;
  954.       ELSE {
  955.        if (strlen(wrd)>0)
  956.         substr(wrd, 0, strlen(wrd)-1, wrd);
  957.        else
  958.         substr(ans, 0, strlen(ans)-1, ans);
  959.         host_send_c(i);
  960.        }
  961.      }
  962.    ELSE
  963.      {
  964.       strcat(wrd, i);
  965.       if ((i==' ') && (cnt<80)) {
  966.         strcat(ans, wrd);
  967.         wrd="";
  968.       }
  969.       IF (CNT>=80)
  970.         {
  971.          cnt=strlen(wrd);
  972.          do {
  973.            cnt=cnt-1;
  974.            host_send_c(8);
  975.           }
  976.          while (cnt>0);
  977.          cnt=strlen(wrd);
  978.          do {
  979.            cnt=cnt-1;
  980.            host_send_c(' ');
  981.           }
  982.          while (cnt>0);
  983.          host_send("^M^J");
  984.          strcat(ans, "^m");
  985.          fputs(ans, f);
  986.          host_send(wrd);
  987.          ANS=wrd;
  988.          wrd="";
  989.          CNT=strlen(ans)+1;
  990.         }
  991.      }
  992.   }
  993.  while (MSSGDONE==0);
  994.  host_send("^M^J");
  995.  fclose(f);
  996.  host_send(" Send Message? Y/n: ");
  997.  i='a';
  998.  do
  999.   i=toupper(host_input(1));
  1000.  while ((i!='Y') and (i!='N'));
  1001.  host_send("^M^J^M^J");
  1002.  IF (i=='Y')
  1003.    {
  1004.     mssg_from=current_caller;
  1005.     ans="";
  1006.     do
  1007.      {
  1008.       ans=host_message;
  1009.       strcat(ans, "M");
  1010.       mssg_num=random(10000)*100+random(100);
  1011.       itos(mssg_num, fn);
  1012.       strcat(ans, fn);
  1013.       strcat(ans, ".msg");
  1014.       if (filefind(ans, 0)) ans="";
  1015.      }
  1016.     while (ans=="");
  1017.     frename("edit.msg", ans);
  1018.     fseek(ndx_fil, 0, 2);
  1019.     mssg_time=curtime();
  1020.     ndx_write(0);;
  1021.    }
  1022.  else
  1023.    {
  1024.     fdelete("edit.msg");
  1025.    }
  1026. }
  1027.  
  1028.  
  1029. // Mark message record for deletion and delete message file
  1030. delete_mssg(int m_num)
  1031. {
  1032.  int position;
  1033.  str filnam[64], buf[64];
  1034.  position=ftell(ndx_fil);
  1035.  if (position==0) position=filesize(ndx_fil);
  1036.  position=position-110;
  1037.  do
  1038.   {
  1039.    fseek(ndx_fil, position, 0);
  1040.    ndx_read();
  1041.    if (mssg_num==m_num)
  1042.     {
  1043.      mssg_priv=2;
  1044.      fseek(ndx_fil, position, 0);
  1045.      ndx_write(0);;
  1046.      // delete message file
  1047.      itos(mssg_num, filnam);
  1048.      filnam=strcat("M", filnam);
  1049.      buf=host_message;
  1050.      filnam=strcat(buf, filnam);
  1051.      strcat(filnam, ".msg");
  1052.      fdelete(filnam);
  1053.      return;
  1054.     }
  1055.    position=position-110;
  1056.   }
  1057.  while (position > 0);
  1058. }
  1059.  
  1060.  
  1061. // Delete old and marked messages
  1062. update_ndx_file()
  1063. {
  1064.  str filnam[80];  //the new temp ndx filename
  1065.  str buf[80];     //general purpose & old ndx filename
  1066.  int f, tim;
  1067.  prints("Updating Message Index File");
  1068.  filnam = host_message;
  1069.  strCat(filnam, "temp.ndx");
  1070.  f=fopen(filnam, "w");
  1071.  fseek(ndx_fil, 0, 0);
  1072.  ndx_read();
  1073.  mssg_time=tim=curtime();
  1074.  ndx_write(f);
  1075.  mssg_time=0;
  1076.  do {
  1077.   if (!ndx_read())
  1078.    {
  1079.     mssg_time=tim;
  1080.     mssg_priv=2;
  1081.    }
  1082.   else
  1083.    if ((tim-mssg_time) > 684800)
  1084.     {
  1085.      // delete Old files
  1086.      buf="M";
  1087.      itos(mssg_num, filnam);
  1088.      filnam=strcat(buf, filnam);
  1089.      buf=host_message;
  1090.      filnam=strcat(buf, filnam);
  1091.      strcat(filnam, ".msg");
  1092.      fdelete(filnam);
  1093.     }
  1094.  } while ((tim-mssg_time) > 684800);    // one week
  1095.  do {
  1096.   if (mssg_priv < 2) ndx_write(f);
  1097.  } while (ndx_read());
  1098.  fclose(f);
  1099.  fclose(ndx_fil);
  1100.  filnam=host_message;
  1101.  strcat(filnam, "temp.ndx");
  1102.  buf=host_message;
  1103.  strcat(buf, "message.ndx");
  1104.  fdelete(buf);
  1105.  frename(filnam, buf);
  1106.  ndx_fil=fopen(buf, "r+");
  1107. }
  1108.  
  1109.  
  1110. ndx_read() {
  1111.  str buf[110], buf2[10];
  1112.  int n;
  1113.  if (feof(ndx_fil)) return 0;
  1114.  fread(buf, 110, ndx_fil);
  1115.  substr(buf, 0, 9, buf2);
  1116.  mssg_num=stoi(buf2);
  1117.  substr(buf, 9, 1, buf2);
  1118.  mssg_priv=stoi(buf2);
  1119.  substr(buf, 10, 31, mssg_to);
  1120.  do {
  1121.   substr(mssg_to, 0, strlen(mssg_to)-1, mssg_to);
  1122.  } while (subchr(mssg_to, strlen(mssg_to)-1)==' ');
  1123.  substr(buf, 40 , 31, mssg_from);
  1124.  do {
  1125.   substr(mssg_from, 0, strlen(mssg_from)-1, mssg_from);
  1126.  } while (subchr(mssg_from, strlen(mssg_from)-1)==' ');
  1127.  substr(buf, 70, 10, buf2);
  1128.  mssg_time=stoi(buf2);
  1129.  substr(buf, 80, 30, mssg_subj);
  1130.  return 1;
  1131. }
  1132.  
  1133. ndx_write(int fl)
  1134. {
  1135.  str buf[30];
  1136.  int hold_ndx;
  1137.  if (fl!=0)
  1138.   {
  1139.    hold_ndx=ndx_fil;
  1140.    ndx_fil=fl;
  1141.   }
  1142.  itos(mssg_num, buf);
  1143.  if (strlen(buf)<9)
  1144.   do
  1145.    strcat(buf, " ");
  1146.   while (strlen(buf) < 9);
  1147.  fwrite(buf, 9, ndx_fil);
  1148.  itos(mssg_priv, buf);
  1149.  fwrite(buf, 1, ndx_fil);
  1150.  buf=mssg_to;
  1151.  if (strlen(buf) < 30)
  1152.   do
  1153.    strcat(buf, " ");
  1154.   while (strlen(buf) < 30);
  1155.  fwrite(buf, 30, ndx_fil);
  1156.  buf=mssg_from;
  1157.  if (strlen(buf) < 30)
  1158.   do
  1159.    strcat(buf, " ");
  1160.   while (strlen(buf) < 30);
  1161.  fwrite(buf, 30, ndx_fil);
  1162.  itos(mssg_time, buf);
  1163.  if (strlen(buf)<10)
  1164.   do
  1165.    strcat(buf, " ");
  1166.   while (strlen(buf) < 10);
  1167.  fwrite(buf, 10, ndx_fil);
  1168.  if (strlen(mssg_subj)<30)
  1169.   do
  1170.    strcat(mssg_subj, " ");
  1171.   while (strlen(mssg_subj) < 30);
  1172.  fwrite(mssg_subj, 30, ndx_fil);
  1173.  if (fl!=0) ndx_fil=hold_ndx;
  1174. }
  1175.  
  1176.  
  1177. //////////////////////////////////////////////////////////////////////////////
  1178.  
  1179. type_our_file(str fname) {
  1180.   int f;
  1181.   str s[144];
  1182.  
  1183.   if ((f=type_file(fname)) == -1) {
  1184.     s=our_dir;
  1185.     strcat(s,fname);
  1186.     f=type_file(s);
  1187.     }
  1188.   return f;
  1189. }
  1190.  
  1191. //////////////////////////////////////////////////////////////////////////////
  1192.  
  1193. type_file(str fname) {
  1194.  
  1195.   int f, r_a_fl;
  1196.   str s[80];
  1197.   str buf[255], fname_b[80], fname_x[80];
  1198.   int cnt, ichar;
  1199.   int lines_sent = 0;
  1200.  
  1201.   r_a_fl=0;
  1202. //  fname_x = our_dir;
  1203.   strCat(fname_x, fname);
  1204.  
  1205.   if (strposi(fname, "." )==-1)
  1206.   {
  1207.     r_a_fl=2;
  1208.     fname_b=fname_x;
  1209.     strcat(fname_b, ".rip");
  1210.     if ((rip_on) and (filefind(fname_b, 0) != 0)) {}
  1211.     else
  1212.     {
  1213.       r_a_fl=1;
  1214.       fname_b=fname_x;
  1215.       strcat(fname_b, ".ans");
  1216.       if ((ansi_on) and (filefind(fname_b, 0) != 0)) {}
  1217.       else
  1218.       {
  1219.         r_a_fl=0;
  1220.         fname_b=fname_x;
  1221.         strcat(fname_b, ".txt");
  1222.       }
  1223.     }
  1224. //   fname=fname_b;
  1225.   }
  1226.   else
  1227.     fname_b=fname;
  1228.   f = fopen(fname_b, "r");
  1229.   if (!f)
  1230.     return -1;
  1231.  
  1232.   host_send("^M^J^J");
  1233.  
  1234.   while (1) {
  1235.     if (carrier_counts)
  1236.       if (!carrier()) {
  1237.         connection_lost = 1;
  1238.         finished_caller = 1;
  1239.         fclose(f);
  1240.         return 0;
  1241.       }
  1242.  
  1243.   if (R_A_Fl > 0) {
  1244.     if ((cnt=fread(buf, strMaxLen(buf), f)) <= 0) {
  1245.       fclose(f);
  1246.       return 1;
  1247.       }
  1248.     setchr(buf, cnt, 0);
  1249.     }
  1250.   else {
  1251.     if (fgets(buf, 80, f) == -1) {
  1252.       fclose(f);
  1253.       return 1;
  1254.     }
  1255.   }
  1256.   host_send(buf);
  1257.   if (r_a_fl==0) {
  1258.     host_send("^M^J");
  1259.     ++lines_sent;
  1260.  
  1261.     if (lines_sent >= 22) {
  1262.       lines_sent = 0;
  1263.       host_send("[More]");
  1264.       host_input(1);
  1265.  
  1266.       if (finished_caller) {       // if user inactivity
  1267.         fclose(f);
  1268.         return 0;
  1269.       }
  1270.  
  1271.       host_send("^H ^H^H ^H^H ^H^H ^H^H ^H^H ^H^H ^H");
  1272.     }
  1273.   }
  1274.     while (cinp_cnt()) {
  1275.       ichar = cgetc();
  1276.       if (ichar == '^C' || ichar == '^K') {
  1277.         host_send("^M^J");
  1278.         fclose(f);
  1279.         return 1;
  1280.       }
  1281.     }
  1282.   }
  1283. }
  1284.  
  1285. //////////////////////////////////////////////////////////////////////////////
  1286.  
  1287. host_send(str outstr) {
  1288.  
  1289.   printsc_trm(outstr);
  1290.   if (!local_mode)
  1291.     cputs(outstr);
  1292.  
  1293. }
  1294.  
  1295. //////////////////////////////////////////////////////////////////////////////
  1296.  
  1297. host_send_c(int chr) {
  1298.  
  1299.   printc(chr);
  1300.   if (!local_mode)
  1301.     cputc(chr);
  1302.  
  1303. }
  1304.  
  1305. //////////////////////////////////////////////////////////////////////////////
  1306.  
  1307. host_input_strn(str buf, int maximum, int echoable) {
  1308.  
  1309.   int i = 0, key;
  1310.  
  1311.   while (1) {
  1312.     key = host_input(echoable);
  1313.     if (!key) {               // timeout or user disconnect
  1314.       setchr(buf, 0, 0);      // set string to empty
  1315.       return 0;               // indicate there is a problem
  1316.     }
  1317.  
  1318.     if (key == '^M') {
  1319. //      if (!echoable) host_send("^H ");
  1320.       break;
  1321.       }
  1322.     if (key == 127 || key == 8) {
  1323.       if (i) {
  1324.         --i;
  1325.         host_send_c(key);
  1326.       }
  1327.       continue;
  1328.     }
  1329.     if (i < maximum)
  1330.       setchr(buf, i, key);
  1331.     ++i;
  1332.     if (maximum<=1) break;  //hotkeys if buffer only holds one
  1333.   }
  1334.  
  1335.   if (i > maximum)
  1336.     i = maximum;
  1337.  
  1338.   setchr(buf, i, '^0');
  1339.  
  1340.   if (subchr(buf, 0))
  1341.     return 1;
  1342.   else
  1343.     return 0;
  1344.  
  1345. }
  1346.  
  1347. //////////////////////////////////////////////////////////////////////////////
  1348.  
  1349. host_input(int echoable) {
  1350.  
  1351.   int c, t;
  1352.  
  1353.   t = timer_start(2400);         // 4 minutes inactivity allowed
  1354.  
  1355.   while (1) {
  1356.     if (time_up(t) && !direct_connect) {
  1357.       host_send("^M^J^M^JInactivity period too long. Connection terminated!^M^J");
  1358.       if (carrier_counts)
  1359.         hangup();
  1360.       finished_caller = 1;
  1361.       kill_user = 1;
  1362.       break;
  1363.     }
  1364.  
  1365.     if (carrier_counts)
  1366.       if (!carrier()) {
  1367.         prints("^M^JConnection has been lost, call terminated.^M^J");
  1368.         connection_lost = 1;
  1369.         finished_caller = 1;
  1370.         break;
  1371.       }
  1372.     if ((c = inkey()) != 0) {
  1373.       if (c == 27) {             // ESC key, sysop wants to exit
  1374.         finished_caller = 1;
  1375.           exit_requested = 1;
  1376.           break;
  1377.       }
  1378.       else if (c == 0x4f00) {    // END key, terminate user
  1379.         prints("^M^JUser terminated!");
  1380.         ustamp("User terminated!", 1, 1);
  1381.         if (carrier_counts)
  1382.           hangup();
  1383.  
  1384.         finished_caller = 1;
  1385.         kill_user = 1;
  1386.         access_level = 0;
  1387.         break;
  1388.       }
  1389.  
  1390.       else if (c <= 255) {
  1391.         if (c != 8 && c != 127)
  1392.           if ((!echoable)&& c != 13)
  1393.             host_send_c('*');
  1394.           else
  1395.             host_send_c(c);
  1396.         break;
  1397.       }
  1398.     }
  1399.  
  1400.     if (!local_mode)
  1401.       if (cinp_cnt())  {
  1402.         c = cgetc();
  1403.         if (c != 8 && c != 127)
  1404.           if ((!echoable)&& c != 13)
  1405.             host_send_c('*');
  1406.           else
  1407.             host_send_c(c);
  1408.         break;
  1409.       }
  1410.   }
  1411.  
  1412.   timer_free(t);                 // free existing timer
  1413.   if (finished_caller)
  1414.     return 0;                    // return 0 - no character
  1415.  
  1416.   return c;                      // return received/pressed character
  1417. }
  1418.  
  1419. //////////////////////////////////////////////////////////////////////////////
  1420.  
  1421.  
  1422. //  This routine maintains an ASCII file in the Telix files directory called
  1423. //    WHPASS.TXT.  The format for each line is:
  1424.  
  1425. //    name;password;working_dir;access_level  (optional comment)
  1426.  
  1427. //    The name, password, working_dir, and access_level fields MUST be
  1428. //    separated by semicolons
  1429.  
  1430. //    The working_dir field is optional (but the semicolons before and after
  1431. //    it are _NOT_).  If there's no working_dir field, the default host
  1432. //    upload and download direcories are used.
  1433.  
  1434. //  The routine searches the file for a line on which the "name" field
  1435. //    matches the global variable "current_caller"  (not case sensitive).
  1436.  
  1437. //  If a match is found, and the user can type a password that matches
  1438. //    the "password" field (not case sensitive), the routine returns
  1439. //    the integer "access_level".
  1440.  
  1441. //  If no match is found, the user is given an opportunity to register
  1442. //    (at access level 1).
  1443.  
  1444. //  If the user registers, the file is updated with the new user name,
  1445. //    password, and access level (1), and the routine returns 1.
  1446.  
  1447. //  If the user does not register, or if the user cannot match the password
  1448. //    in the file in "maxtries",  or if the user registers and cannot match
  1449. //    the password he/she chose in "maxtries", the routine returns 0.
  1450.  
  1451. setup_user (int maxtries) {
  1452.   str password_file[64], line_from_file[127], password_from_file[16],
  1453.       name_from_file[31], temporary[16], typed_password[16],
  1454.       working_dir[64], last_char[1];
  1455.  
  1456.   int password_file_handle, field_length, field_start,
  1457.       found_password = 0, access_from_file, counter = 0,
  1458.       file_ends_in_control_z = 0, line_number = 0, length;
  1459.   password_file = our_dir;
  1460.   strcat (password_file, "WHPASS.TXT");
  1461.  
  1462.   for (counter = 1; counter <= maxtries; counter = counter + 1) {
  1463.                       // Try to open password file
  1464.     if (password_file_handle = fopen (password_file, "r")) {
  1465.                         // Read next line from file.
  1466.       while (fgets (line_from_file, 64, password_file_handle) != -1) {
  1467.                         // Check for ^Z termination
  1468.         if (line_from_file == "^Z") {
  1469.           file_ends_in_control_z = 1;
  1470.           break;
  1471.         }
  1472.         line_number = line_number + 1;
  1473.                       // allow for empty or comment lines
  1474.                       // comment lines begin with ';'
  1475.         if (!strlen(line_from_file) || strchr(line_from_file, 0, ';')) {
  1476.                       // If line is long enough . . .
  1477.           if (strlen (line_from_file) >= min_user_name+4) {
  1478.                       // Get length of name
  1479.             if ( (field_length = strchr (line_from_file, 0, ';')) > 0) {
  1480.                       // Get name
  1481.               substr (line_from_file, 0, field_length, name_from_file);
  1482.                       // If name matches . . . .
  1483.               if (strcmpi (name_from_file, current_caller) == 0) {
  1484.                       // Get password
  1485.                 field_start = field_length + 1;
  1486.                 if ( (field_length = strchr (line_from_file, field_start, ';') - field_start) > 0) {
  1487.                   substr (line_from_file, field_start, field_length, password_from_file);
  1488.                       // Get working directory
  1489.                   field_start = field_start + field_length + 1;
  1490.                   if ( (field_length = strchr (line_from_file, field_start, ';') - field_start) >= 0) {
  1491.                     substr (line_from_file, field_start, field_length, working_dir);
  1492.                       // Get access level
  1493.                     field_start = field_start + field_length + 1;
  1494.                     substr (line_from_file, field_start, 1, temporary);
  1495.                     access_from_file = stoi (temporary);
  1496.                       // Set flag that we got an old user
  1497.                     found_password = 1;
  1498.                     break;
  1499.                   }
  1500.                   else password_file_error (line_number, line_from_file, "no third semicolon");
  1501.                 }
  1502.                 else password_file_error (line_number, line_from_file, "no second semicolon");
  1503.               }
  1504.             }
  1505.             else password_file_error (line_number, line_from_file, "no first semicolon");
  1506.           }
  1507.           else password_file_error (line_number, line_from_file, "line too short");
  1508.         }
  1509.       }
  1510.       fclose (password_file_handle);
  1511.     }
  1512.     else if (password_file_handle = fopen(password_file, 'W')) {  // no password file. Make one.
  1513.       fputs(";WHPASS.TXT - WinHost user data file^M^J", password_file_handle);
  1514.       fputs(";format: <NAME>;<PASSWORD>;<WORK_DIR>;<ACCESS> <COMMENT>^M^J", password_file_handle);
  1515.       fclose(password_file_handle);
  1516.     }
  1517.  
  1518.     if (found_password)
  1519.       break;
  1520.     else {
  1521.       host_send ("^M^JNo user ^"");
  1522.       host_send (current_caller);
  1523.       host_send ("^" on file; ");
  1524.       host_send ("Re-type name? (y/n): ");
  1525.       host_input_strn (temporary, 1, 1);
  1526.       host_send ("^M^J");
  1527.  
  1528.       if (strcmpi(temporary, "y"))
  1529.         break;
  1530.       else
  1531.         get_user_name();
  1532.     }
  1533.   }
  1534.  
  1535.   if (found_password) {
  1536.                       // Password is on file; ask for it
  1537.     host_send ("Password: ");
  1538.     for (counter = 1; counter <= maxtries; ++counter) {
  1539.       host_input_strn (typed_password, 16, 0);
  1540.                       // If a match
  1541.       if (!strcmpi (typed_password, password_from_file)) {
  1542.         host_send ("^M^J");
  1543.           // If the user has a working directory ...
  1544.         if (strlen(working_dir)) {
  1545.             // Check for a "\" on the end and add it if necessary
  1546.           length = strlen(working_dir);
  1547.           substr (working_dir, length - 1, 1, last_char);
  1548.           if (strcmpi (last_char, "\"))
  1549.             strcat (working_dir, "\");
  1550.             // Establish download & upload directories
  1551.           strupper (working_dir);
  1552.           if (check_directory (working_dir)) {
  1553.             _down_dir = working_dir;
  1554.             _up_dir = working_dir;
  1555.             user_has_own_dir = 1;
  1556.           }
  1557.           else {
  1558.             prints ("Using defaults");
  1559.             ustamp (working_dir, 1, 0);
  1560.             ustamp (" does not exist, using default", 0, 1);
  1561.           }
  1562.         }
  1563.           // Return the user's access level
  1564.         return (access_from_file);
  1565.       }
  1566.       if (counter < maxtries) {
  1567.         host_send ("^M^JDoes not match password on file!");
  1568.         host_send ("^M^JRe-type name? (y/N): ");
  1569.         host_input_strn (temporary, 1, 1);
  1570.         host_send ("^M^J^J");
  1571.  
  1572.         if (!strcmpi (temporary, "y")) {
  1573.           get_user_name();
  1574.           host_send("Password: ");
  1575.           }
  1576.         else host_send("Re-type password: ");
  1577.       }
  1578.       else
  1579.         host_send ("^M^JMaximum number of tries exceeded!^M^J");
  1580.  
  1581.     }
  1582.   }
  1583.                       // Password is not on file
  1584.   else if (!closed_sys) {
  1585.                       // Offer chance to register
  1586. //    host_send ("No user  ^"");
  1587. //    host_send (current_caller);
  1588. //    host_send ("^"  found in user file.^M^J");
  1589.     host_send ("Do you want to register? (y/N): ");
  1590.     host_input_strn (temporary, 1, 1);
  1591.     host_send ("^M^J");
  1592.                       // If user doesn't want to register
  1593.     if (not ((temporary == "Y") || (temporary == "y")))
  1594.       return (0);
  1595.                       // If user wants to register
  1596.     for (counter = 1; counter <= maxtries; counter = counter + 1) {
  1597.       host_send ("Pick a password (16 characters maximum): ");
  1598.       host_input_strn (password_from_file, 16, 0);
  1599.     
  1600.       if (strchr(password_from_file, 0, ';') != -1) {
  1601.         host_send("^M^JSemicolons are not allowed in passwords!^M^J");
  1602.         if (counter == maxtries)
  1603.           return (0);
  1604.       }
  1605.       else
  1606.         break;
  1607.     }
  1608.     
  1609.                       // Make sure password is right
  1610.     host_send ("^M^JRe-enter your password to verify: ");
  1611.     for (counter = 1; counter <= maxtries; counter = counter + 1) {
  1612.       host_input_strn (typed_password, 16, 0);
  1613.                       // If all is ok
  1614.       if (strcmpi (typed_password, password_from_file) == 0) {
  1615.                       // Build new line for password file
  1616.         line_from_file = current_caller;
  1617.         strcat (line_from_file, ";");
  1618.         strcat (line_from_file, password_from_file);
  1619.         strcat (line_from_file, ";;1 **NEW USER** ");
  1620.         date (curtime(), temporary);
  1621.         strcat (line_from_file, temporary);
  1622.                       // Open password file for appending
  1623.         password_file_handle = fopen(password_file, 'a');
  1624.         if (file_ends_in_control_z)
  1625.           fseek (password_file_handle, -1, 2);
  1626.                       // Now we can write the line
  1627.         fwrite (line_from_file, strlen (line_from_file), password_file_handle);
  1628.         fwrite ("^M^J", 2, password_file_handle);
  1629.         fclose (password_file_handle);
  1630.         host_send ("^M^J");
  1631.         return (1);   // Return access level
  1632.       }
  1633.       if (counter < maxtries)
  1634.         host_send ("^M^JDoes not match!  Please try again: ");
  1635.       else
  1636.         host_send ("^M^JMaximum number of tries exceeded!^M^J");
  1637.     }
  1638.   }
  1639.   return (0);
  1640. }
  1641.  
  1642. //////////////////////////////////////////////////////////////////////////////
  1643. // A routine to print an error message to the local screen when something
  1644. //    is wrong with the password file
  1645.  
  1646. password_file_error (int line_number, str line, str error_specifier) {
  1647.  
  1648.   str line_number_string[4];
  1649.  
  1650.   itos (line_number, line_number_string);
  1651.  
  1652.   prints ("");
  1653.   printsc ("Bad line ");
  1654.   printsc (line_number_string);
  1655.   prints (" in password file:");
  1656.   printsc ("   ^"");
  1657.   printsc (line);
  1658.   prints ("^"");
  1659.   prints (error_specifier);
  1660.  
  1661.   return (1);
  1662. }
  1663.  
  1664. //////////////////////////////////////////////////////////////////////////////
  1665. // returns TRUE if passed filespec is just a filename. Also handles the
  1666. // forward slash as a path separator.
  1667.  
  1668. just_filename(str filespec) {
  1669.  
  1670.   int slash, space;
  1671.  
  1672.   if (strpos(filespec, ":", 0) != -1)
  1673.     return 0;
  1674.   if (strpos(filespec, "\", 0) != -1)
  1675.     return 0;
  1676.   if ((slash = strpos(filespec, "/")) == -1)
  1677.     return 1;
  1678.  
  1679.   space = strpos(filespec, " ");
  1680.   if (space == -1)
  1681.     return 0;
  1682.   if (space < slash)
  1683.     return 1;
  1684.  
  1685.   return 0;
  1686.  
  1687. }
  1688.  
  1689. //////////////////////////////////////////////////////////////////////////////
  1690.  
  1691. host_show_directory (str dir_spec) {
  1692.   str file_name[13], f_name_ext[12], f_size_str[20], f_date_str[20],
  1693.       f_time_str[20], buffer[80], path[67], full_name[80],
  1694.       temp[26], hours_str[2], minutes_str[2], seconds_str[2];
  1695.  
  1696.   int file_exists, fsize, ftime, lines, dot_pos, bps, seconds,
  1697.       minutes, hours;
  1698.  
  1699.   bps = get_baud (1);
  1700.  
  1701.   fnstrip (dir_spec, 12, path);
  1702.  
  1703.   file_exists = FileFind (dir_spec, 0, file_name);
  1704.  
  1705.   if (!file_exists) {
  1706.     host_send ("^M^JNo matching file found.^M^J");
  1707.   }
  1708.   else {
  1709.     lines = 2;
  1710.     host_send ("        Name          Size      Date     Time^M^J");
  1711.   }
  1712.  
  1713.   while (file_exists) {
  1714.  
  1715.     // Get the file size, as a string, with commas where appropriate
  1716.     fsize = FileSize ("");
  1717.     ItoS (fsize, temp);
  1718.     insert_commas (temp, f_size_str);
  1719.  
  1720.     // Get the file date and time as a string
  1721.     ftime = FileTime ("");
  1722.     Date (ftime, f_date_str);
  1723.     Time (ftime, f_time_str);
  1724.  
  1725.     // Estimate how long it'll take to transfer the file with Zmodem
  1726.     seconds = (fsize*10)/bps;
  1727.     // Guess at about 95% efficiency
  1728.     seconds = seconds + seconds/20;
  1729.     if (seconds == 0) {
  1730.       seconds = 1;
  1731.     }
  1732.     minutes = seconds/60;
  1733.     seconds = seconds - minutes*60;
  1734.     hours = minutes/60;
  1735.     minutes = minutes - hours*60;
  1736.  
  1737.     // Convert the transfer time to a string
  1738.     if (seconds < 10) {
  1739.       ItoS (seconds, temp);
  1740.       seconds_str = "0";
  1741.       strcat (seconds_str, temp);
  1742.     }
  1743.     else {
  1744.       ItoS (seconds, seconds_str);
  1745.     }
  1746.     if (minutes < 10) {
  1747.       ItoS (minutes, temp);
  1748.       minutes_str = "0";
  1749.       strcat (minutes_str, temp);
  1750.     }
  1751.     else {
  1752.       ItoS (minutes, minutes_str);
  1753.     }
  1754.     ItoS (hours, hours_str);
  1755.  
  1756.     // Stuff the buffer with just enough spaces so the periods in the
  1757.     //  file names line up
  1758.     dot_pos = strpos (file_name, ".", 0);
  1759.     if (dot_pos > 0) {
  1760.       substr ("        ", 0, 8 - dot_pos, buffer);
  1761.     }
  1762.     else {
  1763.       substr ("        ", 0, 8 - strlen (file_name), buffer);
  1764.     }
  1765.  
  1766.     // Put the file name into the buffer
  1767.     strcat (buffer, file_name);
  1768.  
  1769.     // Append just enough spaces to the buffer to make the right sides of
  1770.     //  the file sizes line up
  1771.     substr ("              ", 0, 26 - strlen (buffer) - strlen (f_size_str), temp);
  1772.     strcat (buffer, temp);
  1773.  
  1774.     // Put the file size into the buffer
  1775.     strcat (buffer, f_size_str);
  1776.  
  1777.     // Put the file date and time into the buffer
  1778.     strcat (buffer, "  ");
  1779.     strcat (buffer, f_date_str);
  1780.     strcat (buffer, " ");
  1781.     strcat (buffer, f_time_str);
  1782.  
  1783.     // Put the transfer time into the buffer
  1784. //  if (hours < 10) {
  1785. //    strcat (buffer, "   ");
  1786. //  }
  1787. //  else {
  1788. //    strcat (buffer, "  ");
  1789. //  }
  1790. //  strcat (buffer, hours_str);
  1791. //  strcat (buffer, ":");
  1792. //  strcat (buffer, minutes_str);
  1793. //  strcat (buffer, ":");
  1794. //  strcat (buffer, seconds_str);
  1795.  
  1796.     // See if we've filled a screen yet ...
  1797.     if (lines > 23) {
  1798.       host_send ("[More]");
  1799.       host_input (1);
  1800.       lines = 0;
  1801.     }
  1802.     else {
  1803.       lines = lines + 1;
  1804.     }
  1805.  
  1806.     // Send the line
  1807.     host_send (buffer);
  1808.     host_send ("^M^J");
  1809.  
  1810.     file_exists = FileFind ("", 0, file_name);
  1811.   }
  1812.  
  1813. }
  1814.  
  1815. //////////////////////////////////////////////////////////////////////////////
  1816.  
  1817. get_extension(str file_name, str result) {
  1818.    int dot_pos;
  1819.    dot_pos = strpos (file_name, ".", 0);
  1820.    result = "";
  1821.    if (dot_pos > 0) {
  1822.      substr(file_name, dot_pos+1, 3, result);
  1823.    }
  1824. }
  1825.  
  1826. // Insert commas into a string representation of an integer, up to
  1827. //  999,999,999,999 (the largest SALT integer is 2,147,483,647)
  1828.  
  1829. insert_commas (str input, str output) {
  1830.  
  1831.   str tmp1[15], tmp2[15];
  1832.   int len, delta;
  1833.  
  1834.   output = input;
  1835.  
  1836.   for (delta = 3; delta <= 11; delta = delta + 4) {
  1837.     if ((len = strlen (output)) > delta) {
  1838.       substr (output, 0, len - delta, tmp1);
  1839.       substr (output, len - delta, 15, tmp2);
  1840.       output = tmp1;
  1841.       strcat (output, ",");
  1842.       strcat (output, tmp2);
  1843.     }
  1844.     else {
  1845.       break;
  1846.     }
  1847.   }
  1848. }
  1849.  
  1850. //////////////////////////////////////////////////////////////////////////////
  1851.  
  1852. send_goodbye () {
  1853.   str s[80];
  1854.  
  1855.   if (type_our_file("GOODBYE") == -1)
  1856.     host_send ("^M^JGoodbye^M^J");
  1857.  
  1858.   delay_scr(20);
  1859. }
  1860.  
  1861. //////////////////////////////////////////////////////////////////////////////
  1862.  
  1863. get_user_name() {
  1864.   int tries=5;
  1865.   str temporary[1];
  1866.  
  1867.   while (tries) {
  1868.     host_send("Please enter your full name: ");
  1869.     host_input_strn(current_caller, 30, 1);
  1870.     host_send("^M^J");
  1871.  
  1872.     if (finished_caller) {
  1873.       access_level = 0;
  1874.       return 0;
  1875.     }
  1876.  
  1877.     if (strchr(current_caller, 0, ';') != -1)
  1878.       host_send("Semicolons are not allowed in user names!^M^J");
  1879.     else if (strlen(current_caller) >= min_user_name)
  1880.       break;
  1881.     else
  1882.       host_send ("Name too short!^M^J");
  1883.     --tries;
  1884.   }
  1885.   return (tries>0);
  1886. }
  1887.